/*
 * Copyright (C) 2005-2006 WIS Technologies International Ltd.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and the associated README documentation file (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
// A "ServerMediaSubsession" subclass for on-demand unicast streaming
// of MPEG-4 video from a WIS GO7007 capture device.
// Implementation

#include "MPEG4VideoServerMediaSubsession.hh"
#include <MPEG4ESVideoRTPSink.hh>
#include <MPEG4VideoStreamDiscreteFramer.hh>

MPEG4VideoServerMediaSubsession*
MPEG4VideoServerMediaSubsession::createNew(UsageEnvironment& env, MediaInput& input, unsigned estimatedBitrate) {
	return new MPEG4VideoServerMediaSubsession(env, input, estimatedBitrate);
}

MPEG4VideoServerMediaSubsession::MPEG4VideoServerMediaSubsession(UsageEnvironment& env, MediaInput& input,
				     unsigned estimatedBitrate)
	: RealMediaSubsession(env, input, estimatedBitrate),
	  fDoneFlag(0) {
}

MPEG4VideoServerMediaSubsession::~MPEG4VideoServerMediaSubsession() {
}

static void afterPlayingDummy(void* clientData) {
	MPEG4VideoServerMediaSubsession* subsess = (MPEG4VideoServerMediaSubsession*)clientData;
	// Signal the event loop that we're done:
	subsess->setDoneFlag();
}

static void checkForAuxSDPLine(void* clientData) {
	MPEG4VideoServerMediaSubsession* subsess = (MPEG4VideoServerMediaSubsession*)clientData;
	subsess->checkForAuxSDPLine1();
}

void MPEG4VideoServerMediaSubsession::checkForAuxSDPLine1() {
	if (fDummyRTPSink->auxSDPLine() != NULL) {
		// Signal the event loop that we're done:
		setDoneFlag();
	} else {
		// try again after a brief delay:
		int uSecsToDelay = 100000; // 100 ms
		nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecsToDelay, (TaskFunc*)checkForAuxSDPLine, this);
	}
}

char const* MPEG4VideoServerMediaSubsession::getAuxSDPLine(RTPSink* rtpSink, FramedSource* inputSource) {
	// Note: For MPEG-4 video buffer, the 'config' information isn't known
	// until we start reading the Buffer.  This means that "rtpSink"s
	// "auxSDPLine()" will be NULL initially, and we need to start reading
	// data from our buffer until this changes.
	fDummyRTPSink = rtpSink;

	// Start reading the buffer:
	fDummyRTPSink->startPlaying(*inputSource, afterPlayingDummy, this);

	// Check whether the sink's 'auxSDPLine()' is ready:
	checkForAuxSDPLine(this);

	envir().taskScheduler().doEventLoop(&fDoneFlag);

	char const* auxSDPLine = fDummyRTPSink->auxSDPLine();
	return auxSDPLine;
}

FramedSource*
MPEG4VideoServerMediaSubsession::createNewStreamSource(unsigned /*clientSessionId*/, unsigned& estBitrate) {
	estBitrate = fEstimatedKbps;

	// Create a framer for the Video Elementary Stream:
	return MPEG4VideoStreamDiscreteFramer::createNew(envir(), fInput.videoSource());
}

RTPSink* MPEG4VideoServerMediaSubsession::createNewRTPSink(Groupsock* rtpGroupsock,
		   unsigned char rtpPayloadTypeIfDynamic,
		   FramedSource* /*inputSource*/) {
	setVideoRTPSinkBufferSize();
	return MPEG4ESVideoRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic);
}
